/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;

namespace DaveSexton.DocProject.ExternalUI
{
	internal sealed class Host : MarshalByRefObject, IEnvironmentHost
	{
		#region Public Properties
		public IWin32Window MainWindow
		{
			get
			{
				return form;
			}
		}

		public string Status
		{
			get
			{
				return form.Status;
			}
			set
			{
				if (form.InvokeRequired)
				{
					form.Invoke((MethodInvoker) delegate()
					{
						form.Status = value;
					});
				}
			}
		}
		#endregion

		#region Private / Protected
		private readonly ProgramForm form;
		private readonly IServiceProvider services;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="Host" /> class.
		/// </summary>
		public Host(ProgramForm form)
		{
			if (form == null)
				throw new ArgumentNullException("form");

			this.form = form;
			this.services = form.Services;

			ProjectManager manager = form.ProjectManager;

			manager.ProjectSaved += manager_Save;
			manager.ProjectOpened += manager_Opened;
			manager.ProjectClosed += manager_Closed;
			manager.BuildComplete += manager_BuildComplete;
		}
		#endregion

		#region Methods
		[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand,
			Flags = System.Security.Permissions.SecurityPermissionFlag.Infrastructure)]
		public override object InitializeLifetimeService()
		{
			return null;
		}

		public void ShowTrace()
		{
			form.Invoke((MethodInvoker) delegate()
			{
				form.ShowBuildTrace();
			});
		}
		#endregion

		#region Events
		private readonly object ProjectSavedEventLock = new object();
		private EventHandler<DocProjectEventArgs> ProjectSavedEvent;
		private readonly object ProjectOpenedEventLock = new object();
		private EventHandler<DocProjectEventArgs> ProjectOpenedEvent;
		private readonly object ProjectClosedEventLock = new object();
		private EventHandler<DocProjectEventArgs> ProjectClosedEvent;
		private readonly object ProjectBuildCompleteEventLock = new object();
		private EventHandler<DocProjectEventArgs> ProjectBuildCompleteEvent;

		/// <summary>
		/// Event raised after a DocProject or DocSite project has been built.
		/// </summary>
		public event EventHandler<DocProjectEventArgs> ProjectBuildComplete
		{
			add
			{
				lock (ProjectBuildCompleteEventLock)
				{
					ProjectBuildCompleteEvent += value;
				}
			}
			remove
			{
				lock (ProjectBuildCompleteEventLock)
				{
					ProjectBuildCompleteEvent -= value;
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="ProjectBuildComplete" /> event.
		/// </summary>
		/// <param name="e"><see cref="DocProjectEventArgs" /> object that provides the arguments for the event.</param>
		private void OnProjectBuildComplete(DocProjectEventArgs e)
		{
			EventHandler<DocProjectEventArgs> handler = null;

			lock (ProjectBuildCompleteEventLock)
			{
				handler = ProjectBuildCompleteEvent;
			}

			if (handler != null)
				handler(this, e);
		}

		/// <summary>
		/// Event raised when a DocProject or DocSite project is closed.
		/// </summary>
		public event EventHandler<DocProjectEventArgs> ProjectClosed
		{
			add
			{
				lock (ProjectClosedEventLock)
				{
					ProjectClosedEvent += value;
				}
			}
			remove
			{
				lock (ProjectClosedEventLock)
				{
					ProjectClosedEvent -= value;
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="ProjectClosed" /> event.
		/// </summary>
		/// <param name="e"><see cref="DocProjectEventArgs" /> object that provides the arguments for the event.</param>
		private void OnProjectClosed(DocProjectEventArgs e)
		{
			EventHandler<DocProjectEventArgs> handler = null;

			lock (ProjectClosedEventLock)
			{
				handler = ProjectClosedEvent;
			}

			if (handler != null)
				handler(this, e);
		}

		/// <summary>
		/// Event raised when a DocProject or DocSite project is first opened.
		/// </summary>
		public event EventHandler<DocProjectEventArgs> ProjectOpened
		{
			add
			{
				lock (ProjectOpenedEventLock)
				{
					ProjectOpenedEvent += value;
				}
			}
			remove
			{
				lock (ProjectOpenedEventLock)
				{
					ProjectOpenedEvent -= value;
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="ProjectOpened" /> event.
		/// </summary>
		/// <param name="e"><see cref="DocProjectEventArgs" /> object that provides the arguments for the event.</param>
		private void OnProjectOpened(DocProjectEventArgs e)
		{
			EventHandler<DocProjectEventArgs> handler = null;

			lock (ProjectOpenedEventLock)
			{
				handler = ProjectOpenedEvent;
			}

			if (handler != null)
				handler(this, e);
		}

		/// <summary>
		/// Event raised when a DocProject or DocSite project, or one of its files, is about to be saved.
		/// </summary>
		public event EventHandler<DocProjectEventArgs> ProjectSaved
		{
			add
			{
				lock (ProjectSavedEventLock)
				{
					ProjectSavedEvent += value;
				}
			}
			remove
			{
				lock (ProjectSavedEventLock)
				{
					ProjectSavedEvent -= value;
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="Save" /> event.
		/// </summary>
		/// <param name="e"><see cref="DocProjectEventArgs" /> object that provides the arguments for the event.</param>
		private void OnProjectSaved(DocProjectEventArgs e)
		{
			EventHandler<DocProjectEventArgs> handler = null;

			lock (ProjectSavedEventLock)
			{
				handler = ProjectSavedEvent;
			}

			if (handler != null)
				handler(this, e);
		}
		#endregion

		#region Event Handlers
		private void manager_Save(object sender, DocProjectEventArgs e)
		{
			OnProjectSaved(e);
		}

		private void manager_Opened(object sender, DocProjectEventArgs e)
		{
			OnProjectOpened(e);
		}

		private void manager_Closed(object sender, DocProjectEventArgs e)
		{
			OnProjectClosed(e);
		}

		private void manager_BuildComplete(object sender, DocProjectEventArgs e)
		{
			OnProjectBuildComplete(e);
		}
		#endregion

		#region IServiceProvider Members
		public object GetService(Type serviceType)
		{
			return services.GetService(serviceType);
		}
		#endregion
	}
}
